#include-once
#include <MsgBoxConstants.au3>
#include <StringConstants.au3>
#include 'ScintillaConstants.au3'
#include 'WindowsConstants.au3'
#include 'WinAPI.au3'
#include 'ScintillaBase.au3'

#Region Searching...
Func Scintilla_FindText($hScintilla, $nTextFlag, Const ByRef $sText, $nStartPos, $nEndPos)
	Local $tTextToFind = DllStructCreate($tagSCI_TEXTTOFIND)
	Local $nCurrentCodePage = Scintilla_GetCodePage($hScintilla)
	Switch $nCurrentCodePage
		Case $SC_CP_UTF8
		Case 1200	;UTF-16 little endian (Windows default)
		Case 1201	;UTF-16 big endian
		Case Else
			; Convert text to UTF-16 LE
			; Then convert back to the current code page
	EndSwitch

EndFunc

#EndRegion

#Region Text Retrievel & Modification...
Func Scintilla_InsertText($hScintilla, $nPos, $sText)
	; Testing
	Return	Scintilla_SendMessageStrW($hScintilla, $SCI_INSERTTEXT, $nPos, $sText)

	Local $nCodePage = Scintilla_GetCodePage($hScintilla)
	If ($nCodePage = $SB_UTF8) Then
		Return BinaryToString(DllStructGetData($tBuf, 1), $SB_UTF8)
	Else
;~ 		Local $nDesChars = _WinAPI_MultiByteToWideCharB($nCodePage, 0, $pBuf, $iLen, 0, 0)
;~ 		Local $tDes = DllStructCreate('WCHAR[' & $nDesChars & ']')
;~ 		_WinAPI_MultiByteToWideCharB(Scintilla_GetCodePage($hScintilla), 0, $pBuf, $iLen, _
;~ 					DllStructGetPtr($tDes), $nDesChars)
;~ 		Return DllStructGetData($tDes, 1)

	EndIf
EndFunc

Func Scintilla_AddText($hScintilla, $nLength, $sText)
	; Testing
	Return	Scintilla_SendMessageStrW($hScintilla, $SCI_ADDTEXT, $nLength, $sText)
EndFunc


Func Scintilla_DeleteRange($hScintilla, $nPos, $nLength)
	Return Int(Scintilla_SendMessageW($hScintilla, $SCI_DELETERANGE, $nPos, $nLength))
EndFunc
#EndRegion

#Region Selection & Information...
Func Scintilla_GetCurrentPos($hScintilla)
	Return Int(Scintilla_SendMessageW($hScintilla, $SCI_GETCURRENTPOS, 0, 0))
EndFunc

Func Scintilla_PositionFromLine($hScintilla, $nLine)
	Return Int(Scintilla_SendMessageW($hScintilla, $SCI_POSITIONFROMLINE, $nLine, 0))
EndFunc

Func Scintilla_LineFromPosition($hScintilla, $nPos)
	Return Int(Scintilla_SendMessageW($hScintilla, $SCI_LINEFROMPOSITION, $nPos, 0))
EndFunc

Func _WinAPI_MultiByteToWideCharB($nCodePage, $nFlag, $pSrc, $nSrcBytes, ByRef $pDes, ByRef $nDesChars)
	Return DllCall('kernel32.dll', 'INT', 'MultiByteToWideChar', 'UINT', $nCodePage, 'DWORD', $nFlag, _
					'PTR', $pSrc, 'INT', $nSrcBytes, 'PTR', $pDes, 'INT', $nDesChars)[0]
EndFunc

Func Scintilla_GetLine($hScintilla, $nLine, $bTrimEOL = False)
	Local $iLen = Scintilla_SendMessageW($hScintilla, $SCI_GETLINE, $nLine, 0)
	Local $tBuf = DllStructCreate("byte[" & $iLen & "]")
	Local $pBuf = DllStructGetPtr($tBuf)
	Scintilla_SendMessageW($hScintilla, $SCI_GETLINE, $nLine, $pBuf)
	Local $nCodePage = Scintilla_GetCodePage($hScintilla)
	If ($nCodePage = $SC_CP_UTF8) Then
		Return BinaryToString(DllStructGetData($tBuf, 1), $SC_CP_UTF8)
	Else
		Local $nDesChars = _WinAPI_MultiByteToWideCharB($nCodePage, 0, $pBuf, $iLen, 0, 0)
		Local $tDes = DllStructCreate('WCHAR[' & $nDesChars & ']')
		Local $pDes = DllStructGetPtr($tDes)
		Local $nChars = _WinAPI_MultiByteToWideCharB(Scintilla_GetCodePage($hScintilla), 0, $pBuf, $iLen, _
					$pDes, $nDesChars)
		; TODO: EOL mode
		If ($bTrimEOL) Then $nDesChars -= 2
		Local $tRet = DllStructCreate('WCHAR[' & $nDesChars & ']', $pDes)
		Return SetExtended($nChars, DllStructGetData($tRet, 1))
		; Returned string will unmatch any unicode pattern
		; Return BinaryToString(DllStructGetData($tBuf, 1), $SB_ANSI)
	EndIf
EndFunc

Func Scintilla_GetTextRange($hScintilla, $nStartPos, $nEndPos)
	; TODO
	Return Int(Scintilla_SendMessageW($hScintilla, $SCI_LINEFROMPOSITION, $nPos, 0))
EndFunc

#EndRegion

#Region Text Encoding...
Func Scintilla_GetCodePage($hScintilla)
	Return Scintilla_SendMessageW($hScintilla, $SCI_GETCODEPAGE, 0, 0)
EndFunc
#EndRegion

#Region Multiple Views...
Func Scintilla_GetDoc($hScintilla)
	Return Scintilla_SendMessageW($hScintilla, $SCI_GETDOCPOINTER, 0, 0)
EndFunc

Func Scintilla_SetDoc($hScintilla, $pDoc)
	Return Scintilla_SendMessageW($hScintilla, $SCI_SETDOCPOINTER, 0, $pDoc)
EndFunc

Func Scintilla_CreateDoc($hScintilla)
	Return Scintilla_SendMessageW($hScintilla, $SCI_CREATEDOCUMENT, 0, 0)
EndFunc

Func Scintilla_AddRefDoc($hScintilla, $pDoc)
	Return Scintilla_SendMessageW($hScintilla, $SCI_CREATEDOCUMENT, 0, $pDoc)
EndFunc

Func Scintilla_ReleaseDoc($hScintilla, $pDoc)
	Return Scintilla_SendMessageW($hScintilla, $SCI_RELEASEDOCUMENT, 0, $pDoc)
EndFunc
#EndRegion

#Region Folding...
#EndRegion

#Region -AutoComplete-
Func Scintilla_AutoCShow($hScintilla, $nLenEntered, Const ByRef $sAutoCList)
	If (IsPtr($sAutoCList)) Then
		Return Scintilla_SendMessageW($hScintilla, $SCI_AUTOCSHOW, $nLenEntered, $sAutoCList)
	Else
		Return Scintilla_SendMessageCStrW($hScintilla, $SCI_AUTOCSHOW, $nLenEntered, $sAutoCList)
	EndIf
EndFunc

Func Scintilla_AutoCCancel($hScintilla)
	Return Scintilla_SendMessageW($hScintilla, $SCI_AUTOCCANCEL, 0, 0)
EndFunc

Func Scintilla_AutoCActive($hScintilla)
	Return Int(Scintilla_SendMessageW($hScintilla, $SCI_AUTOCCANCEL, 0, 0))
EndFunc

Func Scintilla_AutoCPosStart($hScintilla)
	Return Int(Scintilla_SendMessageW($hScintilla, $SCI_AUTOCPOSSTART, 0, 0))
EndFunc

Func Scintilla_AutoCComplete($hScintilla)
	Return Int(Scintilla_SendMessageW($hScintilla, $SCI_AUTOCCOMPLETE, 0, 0))
EndFunc

Func Scintilla_AutoCStops($hScintilla, Const ByRef $sAutoCList)
	If (IsPtr($sAutoCList)) Then
		Return Scintilla_SendMessageW($hScintilla, $SCI_AUTOCSTOPS, 0, $sAutoCList)
	Else
		Return Scintilla_SendMessageCStrW($hScintilla, $SCI_AUTOCSTOPS, 0, $sAutoCList)
	EndIf
EndFunc

Func Scintilla_AutoCSetSeparator($hScintilla, $cSeparator)
	If (IsInt($cSeparator) And $cSeparator > 0 And $cSeparator < 255) Then
		Return Scintilla_SendMessageW($hScintilla, $SCI_AUTOCSETSEPARATOR, $cSeparator, 0)
	Else
		Return Scintilla_SendMessageW($hScintilla, $SCI_AUTOCSETSEPARATOR, AscW($cSeparator), 0)
	EndIf
EndFunc

Func Scintilla_AutoCGetSeparator($hScintilla)
	Return Int(Scintilla_SendMessageW($hScintilla, $SCI_AUTOCGETSEPARATOR, 0, 0))
EndFunc

Func Scintilla_AutoCSelect($hScintilla, Const ByRef $sSelect)
	If (IsPtr($sSelect)) Then
		Return Scintilla_SendMessageW($hScintilla, $SCI_AUTOCSELECT, 0, $sSelect)
	Else
		Return Scintilla_SendMessageStrW($hScintilla, $SCI_AUTOCSELECT, 0, $sSelect)
	EndIf
EndFunc

Func Scintilla_AutoCGetCurrent($hScintilla)
	Return Int(Scintilla_SendMessageW($hScintilla, $SCI_AUTOCGETCURRENT, 0, 0))
EndFunc

Func Scintilla_AutoCGetCurrentText($hScintilla, $nLen = 0)
	If ($nLen >= 0) Then
		Local $sText = ''
		Local $aRet = Scintilla_SendMessageStrW($hScintilla, $SCI_AUTOCGETCURRENTTEXT, 0, $sText)
		Return SetExtended($nLen, $sText)
	Else
		Return SetExtended(Scintilla_SendMessageW($hScintilla, $SCI_AUTOCGETCURRENTTEXT, 0, 0), 0)
	EndIf
EndFunc

Func Scintilla_AutoCSetCancelAtStart($hScintilla, $bCancel)
	Return Scintilla_SendMessageW($hScintilla, $SCI_AUTOCSETSEPARATOR, $bCancel, 0)
EndFunc

Func Scintilla_AutoCGetCancelAtStart($hScintilla)
	Return (Scintilla_SendMessageW($hScintilla, $SCI_AUTOCGETSEPARATOR, 0, 0) <> 0)
EndFunc

Func Scintilla_AutoCSetFillups($hScintilla, Const ByRef $sAutoCList)
	If (IsPtr($sAutoCList)) Then
		Return Scintilla_SendMessageW($hScintilla, $SCI_AUTOCSETFILLUPS, 0, $sAutoCList)
	Else
		Return Scintilla_SendMessageCStrW($hScintilla, $SCI_AUTOCSETFILLUPS, 0, $sAutoCList)
	EndIf
EndFunc

Func Scintilla_AutoCSetChooseSingle($hScintilla, $bChooseSingle)
	Return Scintilla_SendMessageW($hScintilla, $SCI_AUTOCSETCHOOSESINGLE, $bChooseSingle, 0)
EndFunc

Func Scintilla_AutoCGetChooseSingle($hScintilla)
	Return Int(Scintilla_SendMessageW($hScintilla, $SCI_AUTOCGETCHOOSESINGLE, 0, 0))
EndFunc

Func Scintilla_AutoCSetIgnoreCase($hScintilla, $bIgnore)
	Return Scintilla_SendMessageW($hScintilla, $SCI_AUTOCSETIGNORECASE, $bIgnore, 0)
EndFunc

Func Scintilla_AutoCGetIgnoreCase($hScintilla)
	Return (Scintilla_SendMessageW($hScintilla, $SCI_AUTOCGETIGNORECASE, 0, 0) <> 0)
EndFunc

Func Scintilla_AutoCSetCaseInsensitiveBehaviour($hScintilla, $nBehaviour)
	Return Scintilla_SendMessageW($hScintilla, $SCI_AUTOCSETCASEINSENSITIVEBEHAVIOUR, $nBehaviour, 0)
EndFunc

Func Scintilla_AutoCGetCaseInsensitiveBehaviour($hScintilla)
	Return Int(Scintilla_SendMessageW($hScintilla, $SCI_AUTOCGETCASEINSENSITIVEBEHAVIOUR, 0, 0))
EndFunc

Func Scintilla_AutoCSetMulti($hScintilla, $nMulti)
	Return Scintilla_SendMessageW($hScintilla, $SCI_AUTOCSETMULTI, $nMulti, 0)
EndFunc

Func Scintilla_AutoCGetMulti($hScintilla)
	Return Int(Scintilla_SendMessageW($hScintilla, $SCI_AUTOCGETMULTI, 0, 0))
EndFunc

Func Scintilla_AutoCSetOrder($hScintilla, $nOrder)
	Return Scintilla_SendMessageW($hScintilla, $SCI_AUTOCSETORDER, $nOrder, 0)
EndFunc

Func Scintilla_AutoCGetOrder($hScintilla)
	Return Int(Scintilla_SendMessageW($hScintilla, $SCI_AUTOCGETORDER, 0, 0))
EndFunc

Func Scintilla_AutoCSetAutoHide($hScintilla, $bAutoHide)
	Return Scintilla_SendMessageW($hScintilla, $SCI_AUTOCSETAUTOHIDE, $bAutoHide, 0)
EndFunc

Func Scintilla_AutoCGetAutoHide($hScintilla)
	Return (Scintilla_SendMessageW($hScintilla, $SCI_AUTOCGETAUTOHIDE, 0, 0) <> 0)
EndFunc

Func Scintilla_AutoCSetDropRestOfWord($hScintilla, $bDropRestOfWord)
	Return Scintilla_SendMessageW($hScintilla, $SCI_AUTOCSETDROPRESTOFWORD, $bDropRestOfWord, 0)
EndFunc

Func Scintilla_AutoCGetDropRestOfWord($hScintilla)
	Return (Scintilla_SendMessageW($hScintilla, $SCI_AUTOCGETDROPRESTOFWORD, 0, 0) <> 0)
EndFunc

Func Scintilla_AutoCRegisterImage($hScintilla, $nType, $aImgData)
	If (IsArray($aImgData) And UBound($aImgData, 0) = 1) Then
		Local $tData = DllStructCreate('INT[' & UBound($aImgData) & ']')
		For $i = 1 To UBound($aImgData)
			DllStructSetData($tData, 1, $aImgData[$i-1], $i)
		Next
		Return Scintilla_SendMessageW($hScintilla, $SCI_REGISTERIMAGE, $nType, DllStructGetPtr($tData))
	ElseIf (IsBinary($aImgData)) Then
		Local $tData = DllStructCreate('BYTE[' & BinaryLen($aImgData) & ']')
		DllStructSetData($tData, 1, $tData)
		Return Scintilla_SendMessageW($hScintilla, $SCI_REGISTERIMAGE, $nType, DllStructGetPtr($tData))
	Else
		Local $tData = DllStructCreate('CHAR[' & StringLen($aImgData) & ']')
		DllStructSetData($tData, 1, $tData)
		Return Scintilla_SendMessageW($hScintilla, $SCI_REGISTERIMAGE, $nType, DllStructGetPtr($tData))
	EndIf
EndFunc

Func Scintilla_AutoCRegisterRGBAImage($hScintilla, $nType, $aImgData)
	If (IsArray($aImgData) And UBound($aImgData, 0) = 1) Then
		Local $tData = DllStructCreate('INT[' & UBound($aImgData) & ']')
		For $i = 1 To UBound($aImgData)
			DllStructSetData($tData, 1, $aImgData[$i-1], $i)
		Next
		Return Scintilla_SendMessageW($hScintilla, $SCI_REGISTERRGBAIMAGE, $nType, DllStructGetPtr($tData))
	ElseIf (IsBinary($aImgData)) Then
		Local $tData = DllStructCreate('BYTE[' & BinaryLen($aImgData) & ']')
		DllStructSetData($tData, 1, $tData)
		Return Scintilla_SendMessageW($hScintilla, $SCI_REGISTERRGBAIMAGE, $nType, DllStructGetPtr($tData))
	Else
		Local $tData = DllStructCreate('CHAR[' & StringLen($aImgData) & ']')
		DllStructSetData($tData, 1, $tData)
		Return Scintilla_SendMessageW($hScintilla, $SCI_REGISTERRGBAIMAGE, $nType, DllStructGetPtr($tData))
	EndIf
EndFunc

Func Scintilla_AutoCClearRegisteredImages($hScintilla)
	Return Scintilla_SendMessageW($hScintilla, $SCI_CLEARREGISTEREDIMAGES, 0, 0)
EndFunc

Func Scintilla_AutoCSetTypeSeparator($hScintilla, $cSeparator)
	If (IsInt($cSeparator) And $cSeparator > 0 And $cSeparator < 255) Then
		Return Scintilla_SendMessageW($hScintilla, $SCI_AUTOCSETTYPESEPARATOR, $cSeparator, 0)
	Else
		Return Scintilla_SendMessageW($hScintilla, $SCI_AUTOCSETTYPESEPARATOR, AscW($cSeparator), 0)
	EndIf
EndFunc

Func Scintilla_AutoCGetTypeSeparator($hScintilla)
	Return Int(Scintilla_SendMessageW($hScintilla, $SCI_AUTOCSETTYPESEPARATOR, 0, 0))
EndFunc

Func Scintilla_AutoCSetMaxHeight($hScintilla, $nRowCount)
	Return Scintilla_SendMessageW($hScintilla, $SCI_AUTOCSETMAXHEIGHT, $nRowCount, 0)
EndFunc

Func Scintilla_AutoCGetMaxHeight($hScintilla)
	Return (Scintilla_SendMessageW($hScintilla, $SCI_AUTOCGETMAXHEIGHT, 0, 0) <> 0)
EndFunc

Func Scintilla_AutoCSetMaxWidth($hScintilla, $nCharCount)
	Return Scintilla_SendMessageW($hScintilla, $SCI_AUTOCSETMAXWIDTH, $nCharCount, 0)
EndFunc

Func Scintilla_AutoCGetMaxWidth($hScintilla)
	Return (Scintilla_SendMessageW($hScintilla, $SCI_AUTOCGETMAXWIDTH, 0, 0) <> 0)
EndFunc
#EndRegion

#Region Calltip...
Func Scintilla_CalltipActive($hScintilla)
	Return (Scintilla_SendMessageW($hScintilla, $SCI_CALLTIPACTIVE, 0, 0) <> 0)
EndFunc

Func Scintilla_CalltipCancel($hScintilla)
	Return Scintilla_SendMessageW($hScintilla, $SCI_CALLTIPCANCEL, 0, 0)
EndFunc

Func Scintilla_CalltipShow($hScintilla, $nPosStart, Const ByRef $sCallTip)
	Return Scintilla_SendMessageCStrW($hScintilla, $SCI_CALLTIPSHOW, $nPosStart, $sCallTip)
EndFunc

Func Scintilla_CalltipSetHlt($hScintilla, $nPosStart, $nPosEnd)
	Return Scintilla_SendMessageW($hScintilla, $SCI_CALLTIPSETHLT, $nPosStart, $nPosEnd)
EndFunc
#EndRegion

#Region Line Ending...
Func Scintilla_GetEOLMode($hScintilla)
	Return Scintilla_SendMessageW($hScintilla, $SCI_GETEOLMODE, 0, 0)
EndFunc
#EndRegion

Func Scintilla_SetReadOnly($hScintilla, $bReadOnly)
	Return Scintilla_SendMessageW($hScintilla, $SCI_SETREADONLY, $bReadOnly, 0)
EndFunc

Func Scintilla_GetReadOnly($hScintilla)
	Return (Scintilla_SendMessageW($hScintilla, $SCI_GETREADONLY, 0, 0) <> 0)
EndFunc


Func Scintilla_WordStartPosition($hScintilla, $nPos, $bOnlyWordChars)
	Return Int(Scintilla_SendMessageW($hScintilla, $SCI_WORDSTARTPOSITION, $nPos, $bOnlyWordChars))
EndFunc

Func Scintilla_WordEndPosition($hScintilla, $nPos, $bOnlyWordChars)
	Return Int(Scintilla_SendMessageW($hScintilla, $SCI_WORDENDPOSITION, $nPos, $bOnlyWordChars))
EndFunc

Func Scintilla_GetCharAt($hScintilla, $nPos)
	Return Int(Scintilla_SendMessageW($hScintilla, $SCI_GETCHARAT, $nPos, 0))
EndFunc

Func Scintilla_SendMessageW($hWnd, $uMsg, $wParam, $lParam)
	Return DllCall("user32.dll", "LRESULT", "SendMessageW", _
				"HWND", $hWnd, "UINT", $uMsg, "WPARAM", $wParam, "LPARAM", $lParam)[0]
EndFunc

Func Scintilla_SendMessageStr($hWnd, $uMsg, $wParam, ByRef $lParam)
	Local $aRet = DllCall("user32.dll", "LRESULT", "SendMessage", _
				"HWND", $hWnd, "UINT", $uMsg, "PTR", $wParam, "STR", $lParam)
	$lParam = $aRet[4]
	Return $aRet[0]
EndFunc

Func Scintilla_SendMessageStrW($hWnd, $uMsg, $wParam, ByRef $lParam)
	Local $aRet = DllCall("user32.dll", "LRESULT", "SendMessageW", _
				"HWND", $hWnd, "UINT", $uMsg, "PTR", $wParam, "STR", $lParam)
	$lParam = $aRet[4]
	Return $aRet[0]
EndFunc

Func Scintilla_SendMessageWStrW($hWnd, $uMsg, $wParam, ByRef $lParam)
	Local $aRet = DllCall("user32.dll", "LRESULT", "SendMessageW", _
				"HWND", $hWnd, "UINT", $uMsg, "PTR", $wParam, "WSTR", $lParam)
	$lParam = $aRet[4]
	Return $aRet[0]
EndFunc

Func Scintilla_SendMessageCStrW($hWnd, $uMsg, $wParam, Const ByRef $lParam)
	Return DllCall("user32.dll", "LRESULT", "SendMessageW", _
				"HWND", $hWnd, "UINT", $uMsg, "PTR", $wParam, "STR", $lParam)[0]
EndFunc

Func Scintilla_SendMessageCWStrW($hWnd, $uMsg, $wParam, Const ByRef $lParam)
	Return DllCall("user32.dll", "LRESULT", "SendMessageW", _
				"HWND", $hWnd, "UINT", $uMsg, "PTR", $wParam, "WSTR", $lParam)[0]
EndFunc